﻿// Fill out your copyright notice in the Description page of Project Settings.


#include "Plant.h"
#include "Components/SkeletalMeshComponent.h"
#include "Animation/AnimationAsset.h"
#include "Components/BoxComponent.h"


APlant::APlant():
	bCanOverlap(true),
	bCanScale(true),
	bInWithered(false)
{
	PrimaryActorTick.bCanEverTick = false;
	Box = CreateDefaultSubobject<UBoxComponent>(TEXT("Box"));
	RootComponent = Box;
	PlantMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("PlantMesh"));
	PlantMesh->SetupAttachment(Box);

	// 设置碰撞相关属性
	Box->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
	Box->SetCollisionObjectType(ECollisionChannel::ECC_WorldDynamic);
	Box->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap);
	// 设置可以触发重叠事件
	Box->BodyInstance.bGenerateWakeEvents = true;
	Box->SetUseCCD(true);

	GrowthTimeLine = CreateEditorOnlyDefaultSubobject<UTimelineComponent>(TEXT("GrowthTimeLine"));
	ScaleTimeLine = CreateEditorOnlyDefaultSubobject<UTimelineComponent>(TEXT("ScaleTimeLine"));
	WitheredTimeLine = CreateDefaultSubobject<UTimelineComponent>(TEXT("WitheredTimeLine"));
}

void APlant::BeginPlay()
{
	Super::BeginPlay();

	Init();
}

void APlant::OnConstruction(const FTransform& Transform)
{
	Super::OnConstruction(Transform);
	if (PlantMeshAsset)
	{
		PlantMesh->SetSkeletalMeshAsset(PlantMeshAsset);
	}

	PlantMesh->SetWorldScale3D(FVector(PlantMeshInitSize));
}

void APlant::Init()
{
	if (GrowthCurve)
	{
		GrowthUpdateFloat.BindDynamic(this, &ThisClass::UpdateTimelineCompGrowth);
		GrowthOnFinishFunction.BindDynamic(this, &ThisClass::GrowthOnFinish);
		GrowthTimeLine->AddInterpFloat(GrowthCurve, GrowthUpdateFloat);
		GrowthTimeLine->SetTimelineFinishedFunc(GrowthOnFinishFunction);
	}
	if (ScaleCurve)
	{
		ScaleUpdateFloat.BindDynamic(this, &ThisClass::UpdateTimelineCompScale);
		ScaleOnFinishFunction.BindDynamic(this, &ThisClass::ScaleOnFinish);
		ScaleTimeLine->AddInterpFloat(ScaleCurve, ScaleUpdateFloat);
		ScaleTimeLine->SetTimelineFinishedFunc(ScaleOnFinishFunction);
	}
	if (WitheredCurve)
	{
		WitheredUpdateFloat.BindDynamic(this, &ThisClass::UpdateTimelineCompWithered);
		WitheredOnFinishFunction.BindDynamic(this, &ThisClass::WitheredOnFinish);
		WitheredTimeLine->AddInterpFloat(WitheredCurve, WitheredUpdateFloat);
		WitheredTimeLine->SetTimelineFinishedFunc(WitheredOnFinishFunction);
	}

	GetAllMeshComponent();

	if (PlantMeshAsset)
	{
		PlantMesh->SetSkeletalMeshAsset(PlantMeshAsset);
	}

	PlantMesh->SetWorldScale3D(FVector(PlantMeshInitSize));
}

void APlant::UpdateTimelineCompGrowth(const float Output)
{
	const FVector TempSize = FVector(PlantMeshInitSize) + Output * (PlantMeshSize - FVector(PlantMeshInitSize));
	PlantMesh->SetWorldScale3D(TempSize);
}

void APlant::GrowthOnFinish()
{
	if (bCanScale)
	{
		ScaleTimeLine->SetTimelineLength(1);
		ScaleTimeLine->SetPlayRate(1.f / ScaleTime);
		ScaleTimeLine->PlayFromStart();
	}
}

void APlant::UpdateTimelineCompScale(const float Output)
{
	const FVector TempSize = Output * ScaleSize + PlantMeshSize;
	PlantMesh->SetWorldScale3D(TempSize);
}

void APlant::ScaleOnFinish()
{
}

void APlant::UpdateTimelineCompWithered(const float Output)
{
	for (int64 i = 0; i < AllMeshComponent.Num(); i++)
	{
		if (AllMeshComponent[i])
		{
			AllMeshComponent[i]->SetScalarParameterValueOnMaterials("Withered", Output);
		}
	}
}

void APlant::WitheredOnFinish()
{
	bInWithered = false;
}

/*void APlant::BoxBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
}*/

void APlant::GetAllMeshComponent()
{
	AllMeshComponent.Reset();
	TArray<USceneComponent*> TempChildren;

	PlantMesh->GetChildrenComponents(true, TempChildren);

	if (PlantMesh->GetSkeletalMeshAsset())
	{
		AllMeshComponent.AddUnique(PlantMesh);
	}

	for (auto* a : TempChildren)
	{
		if (UMeshComponent* MeshComponent = Cast<UMeshComponent>(a))
		{
			AllMeshComponent.AddUnique(MeshComponent);
		}
	}
}

void APlant::TriggerOverlapGrowth()
{
	if (bCanOverlap == true)
	{
		bCanOverlap = false;
		GrowthTimeLine->SetTimelineLength(1);
		GrowthTimeLine->SetPlayRate(1.0 / GrowthTime);
		GrowthTimeLine->PlayFromStart();
	}
}

void APlant::TriggerOverlapWithered()
{
	if (bInWithered == false)
	{
		bInWithered = true;
		WitheredTimeLine->SetTimelineLength(1);
		WitheredTimeLine->SetPlayRate(1.0 / WitheredTime);
		WitheredTimeLine->Play();

		if (WitheredAnim)
		{
			PlantMesh->PlayAnimation(WitheredAnim, false);
		}
	}
}

void APlant::TriggerOverlapRevitalize()
{
	if (bInWithered == false)
	{
		bInWithered = true;
		WitheredTimeLine->SetTimelineLength(1);
		WitheredTimeLine->SetPlayRate(1.0 / WitheredTime);
		WitheredTimeLine->Reverse();
		if (RevitalizeAnim)
		{
			PlantMesh->PlayAnimation(RevitalizeAnim, false);
		}
	}
}
